package logica.main;

/**
 * @author todo mundo fez em conjunto
 * Minha parte eh Cadastro, Edicao e Exclusao de Veiculo (Carro e Moto)
 */
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;

import logica.locacao.Cobertura;
import logica.locacao.Plano;
import logica.locacao.Seguro;
import logica.pessoa.Agencia;
import logica.pessoa.Filial;
import logica.pessoa.Locador;
import logica.pessoa.Gerente;
import logica.pessoa.Usuario;
import logica.util.Constantes;
import logica.util.Data;
import logica.util.Endereco;
import logica.util.TipoDeLogradouro;
import logica.util.UF;
import logica.veiculo.Acessorio;
import logica.veiculo.Automovel;
import logica.veiculo.Combustivel;
import logica.veiculo.Cor;
import logica.veiculo.Estado;
import logica.veiculo.Potencia;
import logica.veiculo.Veiculo;

/**
 * @author tarciso
 *
 */
public class Main {
	//Constantes da primeira tela que ira aparecer
	private static final int LOGAR = 1;
	private static final int SAIR_DESLOGADO = 2;
	//Opcoes apos o login de gerente
	private static final int CADASTRAR = 1;
	private static final int EXCLUIR = 2;
	private static final int DESLOGAR = 3;
	private static final int SAIR_LOGADO = 4;
	//Opcoes que podem ser cadastradas/excluidas
	private static final int USUARIO = 1;
	private static final int CLIENTE = 2;
	private static final int VEICULO = 3;
	private static final int SEGURO = 4;
	private static final int PLANO = 5;
	private static final int AGENCIA = 6;
	private static final int VOLTAR = 7;
	
	//Tipos de Usuario
	private static final int LOCADOR = 1;
	private static final int GERENTE = 2;
	
	//Tipos de Veiculo
	private static final int AUTOMOVEL = 1;
	private static final int MOTOCICLETA = 2;
	private static Scanner scanner = new Scanner(System.in);
	
	private static String COMANDO_RETORNO = "voltar";
	private static boolean sair;
	private static Gerente root;
	private static Usuario usuarioAtual;
	private static List<Usuario> usuariosLista;
	private static List<Veiculo> veiculosLista;//Usado na insercao, remocao e edicao de veiculos(carro e moto)
	private static List<Seguro> segurosLista;
	private static List<Agencia> agenciasLista;
	private static List<Plano> planosLista;
	private static Agencia centro;
	private static Agencia aeroporto;
	
	//----------------------Pode ser colado aqui--------------------//
	
	/**
	 * Execucao Principal do Programa
	 * @author U All Everybody!!
	 * @update Melhorias na aparencia do codigo, padronizacao das mensagens de alerta e pedido, etc.
	 * Bem como reengenharia para nao utilizar mais o MainGerente.
	 * @param naoUsado - Programa nao recebe nada na linha de comando
	 * @throws Exception 
	 */
	public static void main(String naoUsado[]) throws Exception{
		try{
			usuariosLista = new ArrayList<Usuario>();
			veiculosLista = new ArrayList<Veiculo>();
			segurosLista = new ArrayList<Seguro>();
			agenciasLista = new ArrayList<Agencia>();
			planosLista = new ArrayList<Plano>();
			List<Acessorio> acessorios = new ArrayList<Acessorio>();
			acessorios.add(Acessorio.P2);
			
			veiculosLista.add(new Automovel("12345", "modelo teste", "marca teste", 2005, 2500, Potencia.CV, Cor.AZUL, Combustivel.FLEX, new Data(), Filial.CENTRO, acessorios, Estado.DISPONIVEL, "MOH3719", 50));
			
			root = new Gerente("Administrador do Sistema", null, null, new Endereco(UF.PB, "Campina Grande", "Bodoocongo", TipoDeLogradouro.Rua, "Aprigio Veloso", 50, "58102000", ""), "12345678901","1234567", new Data(), "Brasileiro","admint", "admint", "0000001");
						
			usuariosLista.add(root);
			
			agenciasLista.add(new Agencia("LocaLisa Centro", null, null,new Endereco(UF.PB, "Campina Grande", "Centro", TipoDeLogradouro.Rua, "Marques do Herval", 50, "58102000", ""), "012345678901234", "Mr. Bean", "01.234.567-8901/23", root));
			agenciasLista.add(new Agencia("LocaLisa Aeroporto", null, null, new Endereco(UF.PB, "Campina Grande", "Catole", TipoDeLogradouro.Rua, "Rua do Aeroporto", 50, "58102000", ""), "567890123456789", "John Locke", "45.678.901-2345/67", null));
			
		}catch(Exception e){
			System.out.println(e.getMessage());
		}
		
		Data hoje = new Data();

		String boas_vindas = Constantes.LOGO+"\tBem-vindo ao Sistema Localisa!\n\n\t<Hoje eh "+hoje.getDataPorExtenso()+">\n";
		
		System.out.print(preSeparadorDeEtapas()+boas_vindas);
		
		while (!sair){
			
			if ( usuarioAtual == null ){
				switch(escolherOpcao(preSeparadorDeEtapas()+statusUsuarioLogado()+posSeparadorDeEtapas()+
						"-Escolha uma opcao a seguir:\n[1]Logar\t[2]Sair\n",2)){
					case LOGAR:{
						try{
							usuarioAtual = fazLogin(); //Faz o login no sistema, e retorna o usuario logado
						}
						catch ( Exception e ){
							System.out.println(e.getMessage());
						}
						break;
					}
					case SAIR_DESLOGADO:{
						System.out.println("-Saindo do sistema...");
						sair = true;
						break;
					}
				}
			}
			else if ( usuarioAtual instanceof Gerente ){
				boolean cadastrar = false;
				boolean excluir = false;
				
				switch(escolherOpcao(preSeparadorDeEtapas()+statusUsuarioLogado()+posSeparadorDeEtapas()+
						"-Escolha uma opcao a seguir:\n[1]Cadastrar  [2]Excluir  [3]Deslogar  [4]Sair\n",4)){
					case CADASTRAR:{
						cadastrar = true;
						break;
					}
					case EXCLUIR:{
						excluir = true;
						break;
					}
					case DESLOGAR:{
						usuarioAtual = null;
						break;
					}
					case SAIR_LOGADO:{
						System.out.println("-Saindo do sistema...");
						sair = true;
						break;
					}
				}
				
				while ( cadastrar || excluir ){
					StringBuilder mensagemDeGuia = new StringBuilder();
					mensagemDeGuia.append("\t<Area do Gerente "+usuarioAtual.getNome()+">\n");
					if ( cadastrar ){
						mensagemDeGuia.append("-O que voce deseja cadastrar: \n");
					}
					else if ( excluir ){
						mensagemDeGuia.append("-O que voce deseja excluir: \n");
					}
					switch(escolherOpcao(mensagemDeGuia.toString()+
							"[1]Usuario  [2]Cliente  [3]Veiculo  [4]Seguro  [5]Plano  [6]Agencia [7]Voltar\n",7)){
						case USUARIO:{
							StringBuilder mensagemDeGuia2 = new StringBuilder();
							if ( cadastrar ){
								mensagemDeGuia2.append("-Que tipo de usuario voce deseja cadastrar: \n");
							}
							else if ( excluir ){
								mensagemDeGuia2.append("-Que tipo de usuario voce deseja excluir: \n");
							}
							switch(escolherOpcao(mensagemDeGuia2.toString()+"[1]Funcionario\t[2]Gerente\n",2)){
								case LOCADOR:{
									if ( cadastrar ){
										cadastraLocador();
									}
									else  if ( excluir ){
										excluirObjetoNaLista(usuariosLista);
									}
									break;
								}
								case GERENTE:{
									if ( cadastrar ){
										cadastraGerente();
									}
									else  if ( excluir ){
										excluirObjetoNaLista(usuariosLista);
									}
									break;
								}
							}
							break;
						}
						case CLIENTE:{
							if ( cadastrar ){
								//TODO
							}
							else  if ( excluir ){
								//TODO
							}
							break;
						}
						
						/**
						 * @author Pedro Rawan Meireles Limeira
						 */
						case VEICULO:{
							StringBuilder mensagemDeGuia3 = new StringBuilder();
							if ( cadastrar ){
								mensagemDeGuia3.append("-Que tipo de veiculo voce deseja cadastrar: \n");
							}
							else if ( excluir ){
								mensagemDeGuia3.append("-Que tipo de veiculo voce deseja excluir: \n");
							}
							switch(escolherOpcao(mensagemDeGuia3.toString()+"[1]Automovel\t[2]Motocicleta\n",2)){
								case AUTOMOVEL:{
									if ( cadastrar ){
										try{
			
											if(cadastraAutomovel()){
												System.out.println("Cadastro realizado com sucesso!");
											}else{
												System.out.println("Cadastro nao realizado!");
											}
										}catch(Exception e){
											System.out.println(e.getMessage());
										}
									}
									else  if ( excluir ){
										excluirObjetoNaLista(veiculosLista);
										//TODO
									}
									break;
								}
								case MOTOCICLETA:{
									if ( cadastrar ){
										//TODO
									}
									else  if ( excluir ){
										//TODO
									}
									break;
								}
							}
							break;
						}
						case SEGURO:{
							if ( cadastrar ){
								System.out.println("-Cadastrando novo seguro...");
								try{
									if(cadastraSeguro()){
										System.out.println("Cadastro realizado com sucesso!");
									}else{
										System.out.println("Cadastro nao realizado!");
									}
								}
								catch ( Exception e ){
									System.out.println(e.getMessage());
								}
							}
							else  if ( excluir ){
								try{
									excluirObjetoNaLista(segurosLista);									
								}
								catch ( Exception e ){
									System.out.println(e.getMessage());
								}
							}
							break;
						}
						case PLANO:{
							if ( cadastrar ){
								System.out.println("-Cadastrando novo plano...");
								try{
									if(cadastraPlano()){
										System.out.println("Cadastro realizado com sucesso!");
									}else{
										System.out.println("Cadastro nao realizado!");
									}
								}
								catch ( Exception e ){
									System.out.println(e.getMessage());
								}
							}
							else  if ( excluir ){
								try{
									excluirObjetoNaLista(planosLista);
								}
								catch ( Exception e ){
									System.out.println(e.getMessage());
								}
							}
							break;
						}
						case AGENCIA:{
							if ( cadastrar ){
								System.out.println("-Cadastrando nova agencia...");
								try{
									if(cadastraAgencia()){
										System.out.println("Cadastro realizado com sucesso!");
									}else{
										System.out.println("Cadastro nao realizado!");
									}
								}
								catch ( Exception e ){
									System.out.println(e.getMessage());
								}
							}
							else  if ( excluir ){
								try{
									excluirObjetoNaLista(agenciasLista);									
								}
								catch ( Exception e ){
									System.out.println(e.getMessage());
								}
							}
							break;
						}
						case VOLTAR:{
							if ( cadastrar ){
								System.out.println("-Operacoes de cadastro finalizadas.\n");
								cadastrar = false;
							}
							else if ( excluir ){
								System.out.println("-Operacoes de exclusao finalizadas.\n");
								excluir = false;
							}
							break;
						}
					}
				}
			}
		}
		System.exit(0);
	}

	/**
	 * Retorna um separador de etapas para ser inserido no comeco da etapa, dividindo cada etapa na tela.
	 * @author Guilherme Santos
	 */
	private static String preSeparadorDeEtapas(){
		return "==================================================\n";
	}
	
	/**
	 * Retorna um separador de etapas para ser inserido no fim da etapa, dividindo cada etapa na tela.
	 * @author Guilherme Santos
	 */
	private static String posSeparadorDeEtapas(){
		return "\n==================================================\n==================================================\n";
	}
	
	private static String statusUsuarioLogado(){
		if ( usuarioAtual == null ){
			return "\t   <Nenhum usuario logado!>\n          (Se logue e bom trabalho!)";
		}
		else{
			return "\t   <"+usuarioAtual.getLogin()+" esta logado!>\n           ("+usuarioAtual.getNome()+")";
		}
	}
	
	/**
	 * Verifica se o usuario deseja voltar a operacao/opcao.
	 * @author Guilherme Santos
	 * @param comando
	 * @throws Exception
	 */
	public static void verificaSeCancelou(String comando) throws Exception{
		if ( comando.equals(COMANDO_RETORNO) ){
			throw new Exception("-Cancelado pelo usuario.");
		}
	}
	
	/**
	 * Mostra uma mensagem e pede para entrar com uma opcao em um certo limite, como reacao a mensagem
	 * @author Guilherme Santos
	 * @param mensagem
	 * @param maximo
	 * @return int
	 * @throws Exception 
	 */
	public static int escolherOpcao(String mensagem, int maximo) {

		System.out.print(mensagem+">: ");

		String escolhidoString = scanner.nextLine(); 
		
		if (escolhidoString.isEmpty()){
			System.out.println("<Voce deve inserir alguma entrada!>\n");
			return escolherOpcao(mensagem, maximo);
		}
		
		try{
			verificaSeCancelou(escolhidoString);
		}
		catch (Exception e){
			System.out.println("<Comando de retorno nao funciona aqui!>");
			return escolherOpcao(mensagem, maximo);
		}
		
		for (int i=0; i<escolhidoString.length(); i++){
			if(!Character.isDigit(escolhidoString.charAt(i))){
				System.out.println("<Entrada nao eh um inteiro valido!>\n");
				return escolherOpcao(mensagem, maximo);
			}			
		}		
		
		int escolhidoInt = Integer.parseInt(escolhidoString);
		
		if ( escolhidoInt <= 0 || escolhidoInt > maximo ){
			System.out.println("<Entrada eh um inteiro valido mas nao esta no intervalo de 1 a "+maximo+"!>\n");
			return escolherOpcao(mensagem, maximo);
		}
		
		return escolhidoInt;
	
	}
		
	/**
	 * Pede login e senha e faz o login, caso estejam corretos, ou trata caso nao existam
	 * @author Guilherme Santos
	 * @update Agora lanca excecao se quiser voltar
	 * @return
	 */
	private static Usuario fazLogin() throws Exception{
		
		String login = retornaStringCorreto("-Login: ");
		
		String senha = retornaStringCorreto("-Senha: ");
		
		Iterator<Usuario> iterador = usuariosLista.iterator();
		
		while(iterador.hasNext()){
			
			Usuario usuarioAtual = iterador.next();
			
						
			if(usuarioAtual.getLogin().equals(login)){
				
				if ( usuarioAtual.getSenha().equals(senha)){
					System.out.println("-Login realizado com sucesso!");
					return usuarioAtual;
				}
				
			}
		}
		System.out.println("<Login ou senha nao existem!>");
		return fazLogin();
	}
	
	/**
	 * Verifica se uma string entrou de maneira legal para ser tratada pelos construtores e pelos sets
	 * @author Pedro Rawan Meireles Limeira
	 * @param mensagem
	 * @param input
	 * @return String
	 * @throws Exception
	 */
	private static String retornaStringCorreto(String mensagem) {
		
		System.out.print("\t"+mensagem);
		String input = scanner.nextLine();
		
		while(!validaString(input)){
			System.out.println("\t"+"Digite novamente! ");
			System.out.print("\n"+"\t"+mensagem);
			input = scanner.nextLine();
		}
		
		return input;
	}
	/**
	 * Valida uma entrada em string recebida
	 * @author Guilherme Santos
	 * @param entrada
	 * @return
	 */
	public static boolean validaString(String entrada) {
		
		scanner = new Scanner( System.in );
		
		if ( entrada.trim().isEmpty() ){
			System.out.println("<Voce deve inserir alguma entrada!>");
			return false;
		}
		
		try{
			verificaSeCancelou(entrada);
		}
		catch (Exception e){
			System.out.println("<Comando de retorno nao funciona aqui!>");
		}
		
		return true;
	}
	/**
	 * @author Pedro Rawan Meireles Limeira
	 * @param mensagem
	 * @param input
	 * @return int
	 */
	private static int retornaInteiroCorreto(String prompt) {
		
		System.out.print("\t"+prompt+": ");
		String input = scanner.nextLine();
		
		while(!validaInteiro(input)){
			System.out.println("\t"+"Digite novamente! ");
			System.out.print("\n"+"\t"+prompt+": ");
			input = scanner.nextLine();
		}
		try{
			return Integer.parseInt(input);
		}catch(Exception e){
			System.out.println("-Opcao invalida");
			return retornaInteiroCorreto(prompt);
		}
	}
	
	/**
	 * @author Pedro Rawan Meireles Limeira
	 * Adiciona na objetos numa determinada List
	 * @param Object - aSerAdicionado
	 * @throws Exception se o objeto for nulo
	 */
	public static void adicionaObjetoNaLista(List lista, Object aSerAdicionado) throws Exception{
		
		if(aSerAdicionado == null){
			throw new Exception("veiculo nao pode ser nulo");
		}
				
		Iterator iterador = lista.iterator();
		boolean existe=false;
				
		while(iterador.hasNext()){
			if(iterador.next().equals(aSerAdicionado)){
				existe = true;
			}
		}
				
		if(existe){
			throw new Exception("veiculo ja existe");
		}
		lista.add(aSerAdicionado);
	}
	
	/**
	 * Remove um objeto de uma lista passada como parametro
	 * @param lista - List
	 * @throws Exception
	 */
	public static void excluirObjetoNaLista(List lista) throws Exception{
		if ( !lista.isEmpty() ){
			int escolhida = escolherOpcao("Selecione um elemento:\n"+listarObjetosNaLista(lista)+"\n["+(lista.size()+1)+"]\nVOLTAR", lista.size()+1);
			if ( escolhida == lista.size()+1 ){
				System.out.println("\t-Cancelado pelo usuario.");
			}
			else{
				lista.remove(escolhida -1);				
			}
		}
		else {
			System.out.println(listarObjetosNaLista(lista));
		}

	}
	
	/**
	 * Lista os objetos a partir de uma lista utilizando o toString dos objetos da lista
	 * @param lista - List
	 * @return String
	 */
	public static String listarObjetosNaLista(List lista){
		
		String retorno="";
		
		if ( lista.isEmpty() ){
			retorno+="Nao ha elementos desse tipo cadastrados!\n";
		}
		
		Iterator iterador = lista.iterator();
		int cont=1;
		
		while(iterador.hasNext()){
			retorno+="["+cont+"]\n"+iterador.next().toString()+"\n";
			cont++;
		}
		return retorno;
	}
	// Pede UF - Itera sobre o array de constantes de UF e retorna a constante escolhida pelo usuario
	
	/**
	 * @author Tarciso Braz de Olveira Filho e Guilherme Santos
	 * @param array O array cuja String formatada sera retornada
	 * @return A String formatada do array
	 */
	public static String listarObjetosNoArray(Object[] array){
		
		String stringDeObjetosDoArray = "\n\nSelecione uma das opcoes abaixo: \n";
		
		for(int i = 0; i < array.length; i++) {
			if ((i + 1) % 5 == 0) {
				stringDeObjetosDoArray += "[" + (i + 1) + "] " + array[i] + "\n";
				
			} else {			
				stringDeObjetosDoArray += "[" + (i + 1) + "] " + array[i] + "\t";
			}
		}
		
		return stringDeObjetosDoArray;
	}
	
	
	
	/**
	 * @author Tarciso Braz de Oliveira e Guilherme Santos
	 * @return Endereco Objeto endereco criado a partir das entradas do usuario
	 * @throws Exception Se os parametros do construtor forem invalidos
	 */
	public static Endereco cadastraEndereco() throws Exception {
				
		UF[] unidadesDaFederacao = UF.values();
		TipoDeLogradouro[] tiposDeLogradouro = TipoDeLogradouro.values();
		
		UF unidadeDaFederacaoEscolhida = unidadesDaFederacao[escolherOpcao(listarObjetosNoArray(unidadesDaFederacao) , unidadesDaFederacao.length) - 1];
		
		// Pede cidade
		String cidade = retornaStringCorreto("Cidade: ");
		
		// Pede bairro
		String bairro = retornaStringCorreto("Bairro: ");
		
		// Pede Tipo de Logradouro - Itera sobre o array de constantes de TipoDeLogradouro e retorna a constante escolhida pelo usuario
		TipoDeLogradouro tipoDeLogradouroEscolhido = tiposDeLogradouro[escolherOpcao(listarObjetosNoArray(tiposDeLogradouro) , tiposDeLogradouro.length) - 1];
		
		// Pede Logradouro
		String logradouro = retornaStringCorreto("Logradouro: ");
		
		// Pede Numero
		int numero = retornaInteiroCorreto("Numero: ");
		
		// Pede CEP
		String cep = retornaStringCorreto("CEP: ");
		
		// Pede Observacao
		String observacao = retornaStringCorreto("Observacao: ");
		
		return new Endereco(unidadeDaFederacaoEscolhida, cidade, bairro, tipoDeLogradouroEscolhido, logradouro, numero, cep, observacao);
		
	}
	
	/**
	 * @author Guilherme Santos 
	 * @param entrada - String
	 * @return boolean
	 */
	public static boolean validaInteiro(String entrada) {
		
		scanner = new Scanner( System.in );
		
		if ( entrada.trim().isEmpty() ){
			System.out.println("<Voce deve inserir alguma entrada!>");
			return false;
		}
		try{
			verificaSeCancelou(entrada);
		}
		catch (Exception e){
			System.out.println("<Comando de retorno nao funciona aqui!>");
		}
		
		for ( int i=0; i<entrada.length(); i++ ){
			if ( !Character.isDigit(entrada.charAt(i)) ){
				return false;
			}
		}
		
		return true;
	}

	/**
	 * Cadastra um novo seguro, pedindo a cobertura e a porcentagem.
	 * @return Seguro - O novo seguro a ser cadastrado
	 * @throws Exception Excecao caso o usuario cancele, ou caso haja algum erro nos parametros do seguro
	 */
	public static boolean cadastraSeguro() throws Exception{

		int escolhida = escolherOpcao(listarObjetosNoArray(Cobertura.values()),Cobertura.values().length-1);
		Cobertura cobertura = Cobertura.values()[--escolhida];
		
		int porcentagem = retornaInteiroCorreto("-Qual a porcentagem: ");
		
		try{
			adicionaObjetoNaLista(segurosLista, new Seguro(cobertura, porcentagem));
			return true;
		}
		catch(Exception e){
			System.out.println(e.getMessage());
			return false;
		}
	}
	
	public static boolean cadastraPlano() throws Exception{

		String codigo = retornaStringCorreto("-Codigo do Plano: ");
		
		int qtdeMarcas = retornaInteiroCorreto("-Quantas marcas: ");
		String[] marcas = new String[qtdeMarcas];
		for ( int i=0; i<qtdeMarcas; i++ ){
			marcas[i] = retornaStringCorreto("-Qual a "+i+"a. marca: ");
		}
		
		ArrayList<String> modelosArray = new ArrayList<String>();
		
		for ( int i=0; i<marcas.length; i++ ){
			modelosArray.add(marcas[i]);
			int qtdeModelos = retornaInteiroCorreto(
					"- Quantos modelos para a marca "+marcas[i]);
			for ( int j=0; j<qtdeModelos; j++ ){
				modelosArray.add(retornaStringCorreto(
						"- Qual o "+j+"o. modelo da marca "+marcas[i]+": "));
			}
		}
		
		String[] modelos = (String[]) modelosArray.toArray();

		ArrayList<Acessorio> acessoriosArray =new ArrayList<Acessorio>();
		StringBuilder acessorio = new StringBuilder();

		while(true){
			
			int escolhida = escolherOpcao(listarObjetosNoArray(Acessorio.values())+"["+Acessorio.values().length+"]VOLTAR\n", Acessorio.values().length+1);

			if(escolhida == Acessorio.values().length+1){
				break;
			}
			else{
				Acessorio acessor = Acessorio.values()[escolhida - 1];
				acessoriosArray.add(acessor);
			}
		}
		
		Acessorio[] acessorios = (Acessorio[]) acessoriosArray.toArray();
		
		int temSeguro = escolherOpcao("Esse plano tem Seguro?\n[1]Sim\t[2]Nao\n",2);
		Seguro seguro = null;
		if ( temSeguro == 1 ){
			if ( !segurosLista.isEmpty() ){
				int escolhido = escolherOpcao("Qual seguro: \n"+listarObjetosNaLista(segurosLista),segurosLista.size());
				seguro = segurosLista.get(--escolhido);
			}
			else{
				System.out.println("Mas nao ha seguros cadastrados!");
			}
		}
		
		double potencia = (double) retornaInteiroCorreto("Qual a potencia do veiculo: ");

		try{
			adicionaObjetoNaLista(planosLista, new Plano(codigo, marcas, modelos, acessorios, seguro, potencia));
			
			return true;
		
		}catch(Exception e){
			System.out.println(e.getMessage());
			return false;
		}
	
	}
	
	/**
	 * @author Pedro Rawan Meireles Limeira
	 * @return boolean - caso o cadastro falhe ele retorna false
	 * @throws Exception
	 */
	public static boolean cadastraAutomovel() throws Exception{
		
		String renavam = null, modelo = null, marca = null, placa = null; 
		int ano, potencia, nivelDoTanque;
		Potencia tipoDePotencia;
		Cor cor;
		Combustivel tipoDeCombustivel;
		Data dataDeAquisicao;
		Agencia agencia;
		List<Acessorio> acessorios;
		Estado estado;
			
		System.out.println("\t\t=======================");
		System.out.println("\t\t Cadastrando Automovel");
		System.out.println("\t\t=======================");
		
		acessorios = new ArrayList<Acessorio>();
		
		//Pede RENAVAM
		renavam = retornaStringCorreto("RENAVAM: ");
		
		//Pede Modelo
		modelo = retornaStringCorreto("Modelo: ");
		
		//Pede Marca
		marca = retornaStringCorreto("Marca: ");
		
		//----Pede Placa-----//
		placa = retornaStringCorreto("Placa: ");
		
		//----Pede Ano----//
		ano = retornaInteiroCorreto("Ano: ");
		
		//----Pede tipo da potencia----//
		int capturaTipoDaPotencia = escolherOpcao("\tSelecione uma unidade para potencia [1]CV [2]HP [3]CC (default HP)", 3);
		if(capturaTipoDaPotencia >=1 && capturaTipoDaPotencia<=3){
			tipoDePotencia = Potencia.values()[capturaTipoDaPotencia - 1];

		}else{
			tipoDePotencia = Potencia.HP;
		}
					
		//----Pede potencia----//
		potencia = retornaInteiroCorreto("Potencia: ");
		
		//----Pede Acessorios----//
		acessorios =new ArrayList<Acessorio>();
		StringBuilder acessorio = new StringBuilder();

		while(true){
			
			int escolhida = escolherOpcao(listarObjetosNoArray(Acessorio.values()), Acessorio.values().length+1);
							
			if(escolhida == Acessorio.values().length+1){
				break;
			}
			else{
				Acessorio acessor = Acessorio.values()[escolhida - 1];
				acessorios.add(acessor);
			}
		}
				
		//----Pede Data de aquisicao----//
		System.out.println("\t"+"---Data da aquisicao---");
		int dia = Main.retornaInteiroCorreto("Dia: ");
		int mes = Main.retornaInteiroCorreto("Mes: ");
		int anoData = Main.retornaInteiroCorreto("Ano: ");
		dataDeAquisicao = new Data(dia, mes, anoData);
		
		
		//----Pede Cor----//
		StringBuilder cores = new StringBuilder();
		
		cores.append("-Selecione uma Cor: \n");
		for ( int i=1; i<=Cor.values().length; i++ ){
			cores.append("\t"+"["+i+"]"+Cor.values()[i-1]+"\n");
		}
		
		int escolhida = escolherOpcao(cores.toString(), Cor.values().length);
		cor = Cor.values()[escolhida - 1];	
		
		//----Pede tipo de combustivel----//
		StringBuilder combustivelTipo = new StringBuilder();
		
		combustivelTipo.append("-Selecione um tipo para o combustivel: \n");
		for ( int i=1; i<=Combustivel.values().length; i++ ){
			combustivelTipo.append("\t"+"["+i+"]"+Combustivel.values()[i-1]+"\n");
		}
		
		escolhida = escolherOpcao(combustivelTipo.toString(), Combustivel.values().length);
		tipoDeCombustivel = Combustivel.values()[escolhida - 1];
		
		//----Pede nivelDoTanque----//
		nivelDoTanque = retornaInteiroCorreto("Nivel do tanque: ");
		
		
		//----Pede Estado do veiculo----//
		StringBuilder estadolTipo = new StringBuilder();
		
		estadolTipo.append("-Selecione o estado do carro: \n");
		for ( int i=1; i<=Combustivel.values().length; i++ ){
			estadolTipo.append("\t"+"["+i+"]"+Estado.values()[i-1]+"\n");
		}
		
		escolhida = escolherOpcao(estadolTipo.toString(), Estado.values().length);
		estado = Estado.values()[escolhida - 1];
		
		//----Pede Agencia na qual o veiculo esta fisicamente----//
		Main.listarObjetosNaLista(agenciasLista);
		
		//Tenta construir adicionar
	
		try{
			Main.adicionaObjetoNaLista(veiculosLista, new Automovel(renavam, modelo, marca, ano,
					potencia, tipoDePotencia, cor,
					tipoDeCombustivel, dataDeAquisicao, null,acessorios, estado, placa, nivelDoTanque));
			
			return true;
		
		}catch(Exception e){
			System.out.println(e.getMessage());
			return false;
		}			
}	
	public static Usuario cadastraUsuario() throws Exception {
		System.out.println("\n\n\t===== Cadastro de Funcionario =====\n\n");
		
		
		// Pede nome
		String nome = retornaStringCorreto("Nome: ");
		
		// Pede telefone
		String telefone = retornaStringCorreto("Telefone: ");
		
		// Pede e-mail
		String email = retornaStringCorreto("E-mail: ");
		
		// Pede CPF
		String cpf = retornaStringCorreto("CPF: ");
		
		// Pede RG
		String rg = retornaStringCorreto("RG: ");
		
		System.out.println("\n\tInforme a data de nascimento.\n\n");
		
		// Pede Dia de Nascimento
		int diaDeNascimento = retornaInteiroCorreto("Dia: ");
		
		// Pede Mes de Nascimento
		int mesDeNascimento = retornaInteiroCorreto("Mes: ");
		
		// Pede Ano de Nascimento
		int anoDeNascimento = retornaInteiroCorreto("Ano: ");
		
		// Pede Naturalidade
		String naturalidade = retornaStringCorreto("Naturalidade: ");
		
		// Pede Login
		String login = retornaStringCorreto("Login: ");
		
		// Pede Senha
		String senha = retornaStringCorreto("Senha: ");
		
		// Pede Matricula
		String matricula = retornaStringCorreto("Matricula: ");
		
		
		Endereco enderecoDoGerente = cadastraEndereco();
			
		Data dataDeNascimento = new Data(diaDeNascimento, mesDeNascimento, anoDeNascimento);
		
		Usuario novoUsuario = new Usuario(nome, telefone, email, enderecoDoGerente, cpf, rg, dataDeNascimento, naturalidade, login, senha, matricula);
		
		return novoUsuario;
	}
			
		
	public static void cadastraGerente() {
		try{
						
			adicionaObjetoNaLista(usuariosLista, (Gerente)cadastraUsuario());
			System.out.println("Gerente cadastrado com sucesso!.");
			
		} catch (Exception e) {
			System.out.println(e.getMessage());
			System.out.println("Gerente nao cadastrado.");
		}		
	}
	
	public static void cadastraLocador() {
		try{
						
			adicionaObjetoNaLista(usuariosLista, (Locador)cadastraUsuario());
			System.out.println("Locador cadastrado com sucesso!.");
			
		} catch (Exception e) {
			System.out.println(e.getMessage());
			System.out.println("Locador nao cadastrado.");
		}		
	}
	
	private static boolean cadastraAgencia() throws Exception{
		
		String nome = retornaStringCorreto("\tNome: ");
		
		String telefone = retornaStringCorreto("\tTelefone: ");
		
		String email = retornaStringCorreto("\tEmail: ");
		
		Endereco endereco = cadastraEndereco();
		
		String cnpj = retornaStringCorreto("\tCNPJ: ");
		
		String razaoSocial = retornaStringCorreto("\tRazao Social: ");
		
		String inscricaoEstadual = retornaStringCorreto("\tInscricao Estadual: ");
		
		Gerente gerente;
		int[] indicesGerentes = new int[usuariosLista.size()];
		for ( int i=0; i<indicesGerentes.length; i++ ){
			indicesGerentes[i] = 0;
		}
		
		for ( int i=0; i<usuariosLista.size(); i++ ){
			if ( usuariosLista.get(i) instanceof Gerente ){
				for ( int j=0; j<indicesGerentes.length; j++ ){
					if ( indicesGerentes[j] != 0 ){
						indicesGerentes[j] = i;
					}
				}
			}
		}
		
		StringBuilder gerentes = new StringBuilder();
		
		gerentes.append("-Qual desses Gerentes deve ser o responsavel pela Agencia?\n");
		
		for ( int i=1; i<=indicesGerentes.length; i++ ){
			gerentes.append("["+i+"]"+usuariosLista.get(indicesGerentes[i-1])+"\n");
		}
		int escolhida = escolherOpcao(gerentes.toString()+"\n["+indicesGerentes.length+1+"]NAO TEM GERENTE",indicesGerentes.length+1);
		if ( escolhida == indicesGerentes.length+1 ){
			System.out.println("-Cancelado pelo usuario.");
			gerente = null;
		}
		else {
			gerente = (Gerente) usuariosLista.get(indicesGerentes[escolhida-1]);
		}
		try{
			adicionaObjetoNaLista(usuariosLista, new Agencia(nome, telefone, email, endereco, cnpj, razaoSocial, inscricaoEstadual, gerente) );
			return true;
		}
		catch (Exception e){
			System.out.println(e.getMessage());
			return false;
		}	
	}
}